/*****************************************************************************
 *
 * Weber State University
 * CS4280 Spring 2010
 * Final Group Assignment
 *
 *
 *   TTTTTT                               CCCCC
 *     TT   EEEEE   A    M   M          CC      C
 *     TT   E      A A   M   M         CC   
 *     TT   E     A   A  MM MM  -----  CC
 *     TT   EEE   AAAAA  M M M  -----  CC
 *     TT   E     A   A  M   M          CC      C
 *     TT   EEEEE A   A  M   M            CCCCC
 *
 *   Jared Pack ---- Jon Mann ---- Joshua Clayton
 *
 *
 * 
 *
 ****************************************************************************/

 /* FILENAME world.cpp
  *
  * Change control Section
  *
  * Team Member: Jon Mann
  * Version: 0.1
  * Date: 04/6/2010
  *     Changed glClearColor() in OnPrepare() to make the sky more "night-like"
  *
  * Team Member: Jon Mann
  * Version: 0.2
  * Date: 04/9/2010
  *     Added player->tick() call in Animate()--this drives the win/lose test in player
  *		Made minor changes in LoadWorld() to accomodate AI changes
  *		Added code to Animate() to report the ground height directly below us
  *  
  * Team Member: Jon Mann
  * Version: 0.3
  * Date: 04/11/2010
  *		Made minor changes to gui calls
  *
  * Team Member: Jon Mann
  * Version: 0.4
  * Date: 04/13/2010
  *		Made minor changes to Animate(), OnPrepare(), and Draw() to reflect new death sequence
  *		Made minor changes to clock to count forward forever (practically) 
  *			instead of backward for 5 minutes
  *
  * Team Member: Jared Pack
  * Version: 0.4
  * Date: 04/15/2010
  *		Added the wall that encloses the scene
  *
  */


#include "world.h"

CWorld::CWorld()
{
// Begin - Phase 12
	terrain = new CTerrain(32, 0.5);
	wall = new Wall();
// End - Phase 12
}

CWorld::~CWorld()
{
	// Begin - Phase 18
	delete gui;
	// End - Phase 18
	// Begin - Phase 12
	delete terrain;
	terrain = NULL;
	delete wall;
	wall = NULL;
    // End - Phase 12
	// Begin - Phase 18
	gui = NULL;
	// End - Phase 18
	// Begin - Phase 19

#ifdef ENABLE_SOUND 
	audioSystem = NULL;
#endif

}

CWorld::CWorld(CCamera *c)
{
	camera = c;
	// Begin - Phase 12
	terrain = new CTerrain(32, 1.0f);
	wall = new Wall();
	// End - Phase 12
	// Begin - Phase 14
	player = new CPlayer;
	player->init();
	// End - Phase 14
	// Begin - Phase 19
#ifdef ENABLE_SOUND 
	audioSystem = new CDirectXAudio;
#endif
	// End - Phase 19
	// Begin - Phase 18
	gui = new CGUI;
	// End - Phase 18
	// Begin - Phase 16
	gameDone = false;
	// End - Phase 16
	// Begin - Phase 14
	player->AttachTo(terrain);
	player->SetCamera(camera);
	player->SetTerrain(terrain);
	// End - Phase 14
	// Begin - Phase 19
#ifdef ENABLE_SOUND 
	audioSystem->PlaySoundDX(audioSystem->iAmbient);

	player->SetAudioSystem(audioSystem);
#endif
	// End - Phase 19
	LoadWorld();
	timeStart = 0.01;			// 300 seconds = 5 minutes
	timeElapsed = 0.01;
	// Begin - Phase 18
	gui->SetCurrentTime(timeStart);
	gui->SetKillCount(0);
	// End - Phase 18
}

void CWorld::Animate(float deltaTime)
{
	// Phase 12 - Begin
	// Phase 13 - Add hardwired 7.0f for player size
	// Phase 14 - Add player-> size back to camera position
	// set camera height based on player position on terrain
	//camera->position.y = terrain->GetHeight(camera->position.x, camera->position.z) + player->size;

	// instead of setting camera height, we're just telling it how far down the ground is
	camera->setGroundHeight(terrain->GetHeight(camera->position.x, camera->position.z) + player->size);
	if (gameDone)
	{
		player->size--; // let the camera fall through ground
	}
	
	if (camera->position.x <= terrain->GetScanDepth())
		camera->position.x = terrain->GetScanDepth();
	if (camera->position.x >= terrain->GetWidth()*terrain->GetMul() - terrain->GetScanDepth())
		camera->position.x = terrain->GetWidth()*terrain->GetMul() - terrain->GetScanDepth();
	if (camera->position.z <= terrain->GetScanDepth())
		camera->position.z = terrain->GetScanDepth();
	if (camera->position.z >= terrain->GetWidth()*terrain->GetMul() - terrain->GetScanDepth())
		camera->position.z = terrain->GetWidth()*terrain->GetMul() - terrain->GetScanDepth();

	terrain->Animate(deltaTime);   // animate terrain
	// Phase 12 - End
	// Phase 15 - Begin
	const type_info &ogro = typeid(COgroEnemy);  // get ogro typeid
	const type_info &sod = typeid(CSodEnemy);    // get sod typeid

	numOgros = CountObjectTypes(ogro);           // count ogros
	numSods = CountObjectTypes(sod);             // count sods
	// Phase 15 - End

	// Begin - Phase 18
	gui->SetKillCount(player->GetKillCount());
	gui->SetCurrentTime(timeStart + timeElapsed);
	// End - Phase 18

	// Phase 16 - Begin
	if (!gameDone)
		timeElapsed += deltaTime;
	//else
	//	timeElapsed = timeStart;
    // Phase 16 - End

	// update the player
	player->Tick();
}

void CWorld::FadeScreen()
{
	glDisable(GL_LIGHTING); // disable lighting
	glPushMatrix();
	glLoadIdentity();
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_TEXTURE_2D);
	glColor4f(0.0f, 0.0f, 0.0f, 0.7f);
	glBegin(GL_QUADS);
	glVertex3f(-5, -5, -3.0);
	glVertex3f(5, -5, -3.0);
	glVertex3f(5, 5, -3.0);
	glVertex3f(-5, 5, -3.0);
	glEnd();
	glColor4f(1.0, 1.0, 1.0, 1.0);
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_BLEND);
	glPopMatrix();
}

void CWorld::SetScreen(int width, int height)
{
	screenWidth = width;
	screenHeight = height;
}

void CWorld::Draw(CCamera *camera)
{
    skybox->Draw(*camera);
	terrain->Draw(camera);
	gui->Draw();

	if (gameDone)
	{
		FadeScreen();
		//if (numOgros + numSods <=0)
		//	gui->DrawWinner();
		//else
			gui->DrawLoser();
	}

	// Draws the 4 sections of wall around the terrain
	for(int i = 0; i < 1500; i = i + 20){
		pos.x = 40 + i;
		pos.z = 40;
		pos.y = terrain->GetHeight(pos.x, pos.z) + 20;
		wall->Draw(pos);
	}
	for(int i = 0; i < 1500; i = i + 20){
		pos.x = 40 + i;
		pos.z = 1545;
		pos.y = terrain->GetHeight(pos.x, pos.z) + 20;
		wall->Draw(pos);
	}
	for(int i = 0; i < 1500; i = i + 20){
		pos.x = 40;
		pos.z = 40 + i;
		pos.y = terrain->GetHeight(pos.x, pos.z) + 20;
		wall->Draw2(pos);
	}
	for(int i = 0; i < 1500; i = i + 20){
		pos.x = 1545;
		pos.z = 40 + i;
		pos.y = terrain->GetHeight(pos.x, pos.z) + 20;
		wall->Draw2(pos);
	}
// End - Phase 18
}

void CWorld::OnPrepare()
{
	// Begin - Phase 12
	//glClearColor(terrain->fogColor[0], terrain->fogColor[1], terrain->fogColor[2], terrain->fogColor[3]);
	glClearColor(0.1f, 0.1f, 0.3f, 1.0f); // night sky
	terrain->Prepare();
	// End - Phase 12
	// Phase 15 - Begin
	if (player->isPlayerDead())
		gameDone = true;
	// Phase 15 - End
	
}


// LoadWorld()
// desc: initializes the world
void CWorld::LoadWorld()
{
	// Phase 15 - Begin
	int enemyIdx = 0;
	int rndInt = 0;

	numOgros = 0;
	numSods = 0;

	srand((unsigned int)time(NULL));
	
	rndInt = (rand() % (MAX_ENEMIES-4)) + 4;	// random # from 4 to MAX
	numOgros = numSods = rndInt;

	// generate skybox
	skybox = new Skybox();
	skybox->LoadTexture(0, "alienskin.bmp");
	skybox->LoadTexture(1, "explosion.bmp");
	skybox->LoadTexture(2, "alienskin.bmp");
	skybox->LoadTexture(3, "alienskin.bmp");
	skybox->LoadTexture(4, "alienskin.bmp");
	skybox->LoadTexture(5, "alienskin.bmp");
	// generate ogros
	for (enemyIdx = 0; enemyIdx < numOgros; enemyIdx++)
	{
		ogroEnemy = new COgroEnemy(5);
		ogroEnemy->AttachTo(terrain);
		ogroEnemy->SetPlayer(player);
		ogroEnemy->SetTerrain(terrain);
		// Phase 19 - Uncomment
#ifdef ENABLE_SOUND 
		ogroEnemy->SetAudioSystem(audioSystem);
#endif
		ogroEnemy->position.x = (float)(rand() % (int)(terrain->GetWidth() * terrain->GetMul()));
		ogroEnemy->position.y = 0.0f;
		ogroEnemy->position.z = (float)(rand() % (int)(terrain->GetWidth() * terrain->GetMul()));
	}

	// generate sods
	for (enemyIdx = 0; enemyIdx < numSods; enemyIdx++)
	{
		sodEnemy = new CSodEnemy(15);
		sodEnemy->AttachTo(terrain);
		sodEnemy->SetPlayer(player);
		sodEnemy->SetTerrain(terrain);
		// Phase 19 - Uncomment
#ifdef ENABLE_SOUND 
		sodEnemy->SetAudioSystem(audioSystem);
#endif
//		sodEnemy->LoadAudio(audioSystem, "chimes.wav", false);
		sodEnemy->position.x = (float)(rand() % (int)(terrain->GetWidth() * terrain->GetMul()));
		sodEnemy->position.y = 0.0f;
		sodEnemy->position.z = (float)(rand() % (int)(terrain->GetWidth() * terrain->GetMul()));
	}

		
  // Phase 15 - End
}
// Phase 15 - Begin
// CountObjectTypes
// desc: counts the number of objects passed as classID in the hierarchy
int CWorld::CountObjectTypes(const type_info &classID)
{
	int count = 0;
	CObject *c1;
	CObject *c2;

	c1 = (CObject*)terrain->childNode;

	while (c1 != NULL)
	{
		c2 = c1;
		do
		{
			if (typeid(*c2) == classID)
				count++;
			c2 = (CObject*)c2->nextNode;
		} while (!c2->IsFirstChild());
//      Phase 19 - Remove the following
//		count--;

		c1 = (CObject*)c1->childNode;
	}

	return count;
}
// Phase 15 - End
